package datastructure.board;

import datastructure.board.elements.*;
import datastructure.deck.Deck;
import datastructure.player.Player;
import common.Position;
import common.GameConstants;

import java.lang.reflect.Array;
import java.util.ArrayList;

/**
 * User: Lars Christian Ersly
 * Date: 03-06-11
 * Time: 14:02
 */
public class Board {
    private ArrayList<Player> players;
    private ArrayList<BoardElement> boardElements;
    private ArrayList<HoleBoardElement> holeElements;
    private ArrayList<LaserEmitterBoardElement> laserElements;
    private ArrayList<WallBoardElement> wallElements;
    private ArrayList<ConveyorBeltElement> conveyorBeltElements;
    private Deck deck;

    public Board(){
        //initiation
        players = new ArrayList<Player>();
        boardElements = new ArrayList<BoardElement>();
        holeElements = new ArrayList<HoleBoardElement>();
        laserElements = new ArrayList<LaserEmitterBoardElement>();
        wallElements = new ArrayList<WallBoardElement>();
        conveyorBeltElements = new ArrayList<ConveyorBeltElement>();

        deck = new Deck();
    }



    //GETTERS

    /**
     * @return returns an array containing all board elements
     */
    public ArrayList<BoardElement> getBoardElements() {
        return boardElements;
    }

    public ArrayList<Player> getPlayers() {
        return players;
    }

    public Deck getDeck() {
        return deck;
    }

    public ArrayList<HoleBoardElement> getHoleElements() {
        return holeElements;
    }

    public ArrayList<LaserEmitterBoardElement> getLaserElements() {
        return laserElements;
    }

    public ArrayList<WallBoardElement> getWallElements() {
        return wallElements;
    }

    public ArrayList<ConveyorBeltElement> getConveyorBeltElements() {
        return conveyorBeltElements;
    }

    //SETTERS / ADDERS

    /**
     * Adds an LaserEmitterBoardElement to the board
     * @param position the position
     * @param length length of the beam
     */
    public void addLaserEmitter(Position position, int length){
        LaserEmitterBoardElement laserEmitterBoardElement = new LaserEmitterBoardElement(position, length);
        boardElements.add(laserEmitterBoardElement);
        laserElements.add(laserEmitterBoardElement);
    }

    /**
     * Construct a conveyorBelt
     * @param position the position and direction of the belt
     * @param beltDirection if the belt should turn or be straight
     * @param expressBelt if the belt is an express version which moves 2 spaces
     */
    public void addConveyorBelt(Position position, ConveyorBeltElement.beltDirection beltDirection, boolean expressBelt){
        ConveyorBeltElement conveyorBeltElement = new ConveyorBeltElement(position,beltDirection, expressBelt);
        boardElements.add(conveyorBeltElement);
        conveyorBeltElements.add(conveyorBeltElement);
    }

    /**
     * Adds an HoleBoardElement to the board
     * @param x x-coordinate
     * @param y y-coordinate
     */
    public void addHole(int x, int y){
        HoleBoardElement boardElement = new HoleBoardElement(x, y);
        boardElements.add(boardElement);
        holeElements.add(boardElement);
    }

    /**
     * Adds an wall to the board
     * @param position the position of the wall
     */
    public void addWall(Position position){
        WallBoardElement wallBoardElement = new WallBoardElement(position);
        boardElements.add(wallBoardElement);
        wallElements.add(wallBoardElement);
    }

    /**
     * Add a new player to the board
     * @param player the new player
     */
    public void addPlayer(Player player){
        player.setColor(GameConstants.playerColors[players.size()]);
        players.add(player);
    }


    /**
     * @return a demo board with all available elements
     */
    public static Board createTestBoard(){
        Board board = new Board();

        //HoleBoardElement
        board.addHole(2, 2);
        board.addHole(2, 3);
        board.addHole(3, 2);
        board.addHole(3, 3);

        //WallBoardElement
        board.addWall(new Position(7,1, GameConstants.direction.north));
        board.addWall(new Position(8,2, GameConstants.direction.east));
        board.addWall(new Position(7,3, GameConstants.direction.south));
        board.addWall(new Position(6,2, GameConstants.direction.west));

        //LASER
        board.addLaserEmitter(new Position(3,4, GameConstants.direction.north), 3);
        board.addLaserEmitter(new Position(4,5, GameConstants.direction.east), 3);
        board.addLaserEmitter(new Position(3,6, GameConstants.direction.south), 3);
        board.addLaserEmitter(new Position(2,5, GameConstants.direction.west), 3);


        //ConveyorBelts Normal straight
        board.addConveyorBelt(new Position(0,10, GameConstants.direction.north), ConveyorBeltElement.beltDirection.forward, false);
        board.addConveyorBelt(new Position(0,8, GameConstants.direction.south), ConveyorBeltElement.beltDirection.forward, false);
        board.addConveyorBelt(new Position(2,10, GameConstants.direction.east), ConveyorBeltElement.beltDirection.forward, false);
        board.addConveyorBelt(new Position(2,8, GameConstants.direction.west), ConveyorBeltElement.beltDirection.forward, false);
        //ConveyorBelts express straight
        board.addConveyorBelt(new Position(4,10, GameConstants.direction.north), ConveyorBeltElement.beltDirection.forward, true);
        board.addConveyorBelt(new Position(4,8, GameConstants.direction.south), ConveyorBeltElement.beltDirection.forward, true);
        board.addConveyorBelt(new Position(6,10, GameConstants.direction.east), ConveyorBeltElement.beltDirection.forward, true);
        board.addConveyorBelt(new Position(6,8, GameConstants.direction.west), ConveyorBeltElement.beltDirection.forward, true);
        //ConveyorBelts Normal LEFT
        board.addConveyorBelt(new Position(8,4, GameConstants.direction.north), ConveyorBeltElement.beltDirection.left, false);
        board.addConveyorBelt(new Position(7,4, GameConstants.direction.west), ConveyorBeltElement.beltDirection.left, false);
        board.addConveyorBelt(new Position(7,5, GameConstants.direction.south), ConveyorBeltElement.beltDirection.left, false);
        board.addConveyorBelt(new Position(8,5, GameConstants.direction.east), ConveyorBeltElement.beltDirection.left, false);
//        //ConveyorBelts express LEFT
        board.addConveyorBelt(new Position(8,6, GameConstants.direction.north), ConveyorBeltElement.beltDirection.left, true);
        board.addConveyorBelt(new Position(7,6, GameConstants.direction.west), ConveyorBeltElement.beltDirection.left, true);
        board.addConveyorBelt(new Position(7,7, GameConstants.direction.south), ConveyorBeltElement.beltDirection.left, true);
        board.addConveyorBelt(new Position(8,7, GameConstants.direction.east), ConveyorBeltElement.beltDirection.left, true);
//        //ConveyorBelts Normal RIGHT
        board.addConveyorBelt(new Position(9,4, GameConstants.direction.north), ConveyorBeltElement.beltDirection.right, false);
        board.addConveyorBelt(new Position(9,5, GameConstants.direction.west), ConveyorBeltElement.beltDirection.right, false);
        board.addConveyorBelt(new Position(10,4, GameConstants.direction.east), ConveyorBeltElement.beltDirection.right, false);
        board.addConveyorBelt(new Position(10,5, GameConstants.direction.south), ConveyorBeltElement.beltDirection.right, false);
        //ConveyorBelts express RIGHT
        board.addConveyorBelt(new Position(9,6, GameConstants.direction.north), ConveyorBeltElement.beltDirection.right, true);
        board.addConveyorBelt(new Position(9,7, GameConstants.direction.west), ConveyorBeltElement.beltDirection.right, true);
        board.addConveyorBelt(new Position(10,6, GameConstants.direction.east), ConveyorBeltElement.beltDirection.right, true);
        board.addConveyorBelt(new Position(10,7, GameConstants.direction.south), ConveyorBeltElement.beltDirection.right, true);



        //PLAYER
        Player testPlayer0 = new Player(board);
        testPlayer0.setCurrentPosition(new Position(8, 8, GameConstants.direction.south));
        board.addPlayer(testPlayer0);

        Player testPlayer1 = new Player(board);
        testPlayer1.setCurrentPosition(new Position(8,9, GameConstants.direction.east));
        board.addPlayer(testPlayer1);

        Player testPlayer2 = new Player(board);
        testPlayer2.setCurrentPosition(new Position(9,9, GameConstants.direction.north));
        board.addPlayer(testPlayer2);

        Player testPlayer3 = new Player(board);
        testPlayer3.setCurrentPosition(new Position(9,8, GameConstants.direction.west));
        board.addPlayer(testPlayer3);

        return board;
    }
}
